home *** CD-ROM | disk | FTP | other *** search
/ Collection of Tools & Utilities / Collection of Tools and Utilities.iso / asmutil / a86v400.zip / A07.DOC < prev    next >
Text File  |  1994-12-21  |  21KB  |  478 lines

  1. CHAPTER 7   THE FLOATING-POINT PROCESSOR
  2.  
  3.  
  4. In this chapter, we'll refer to the various Central Processing
  5. Units (CPUs) as the "86".  Thus "86" refers to either the 8088,
  6. 8086, 80186, 80286, etc.  We'll refer to the various coprocessors
  7. as the "87".  Thus "87" refers to either the 8087, the 287, the
  8. 387, or the special IIT-2C87 processor.
  9.  
  10.  
  11. The 8087 and 287 Coprocessors
  12.  
  13. All IBM-PC's, and most clones, contain a socket for a floating
  14. point coprocessor.  If you shell out between $70 and $200, and
  15. plug the appropriate chip into that socket, then a host of
  16. floating point instructions is added to the assembly language
  17. instruction set.  The 486 DX series has the floating-point
  18. processor built into the main CPU chip.
  19.  
  20. The original IBM-PC, and the XT, accept the original floating
  21. point chip, the 8087.  Later processors accept corresponding
  22. chips: the 287 for the 286, the 387 for the 386, etc.  From a
  23. programming standpoint, the 8087 and 287 are nearly identical:
  24. the 287 adds the instructions FSETPM and FSTSW AX, and ignores
  25. the instructions FENI and FDISI.  There is, however, a rather
  26. nasty design flaw in the 8087, that was corrected in the 287.
  27.  
  28. To understand the flaw, you must understand how the 86 and 87
  29. work as coprocessors. Whenever the 86 sees a floating point
  30. instruction, it communicates the instruction, and any associated
  31. memory operands, to the 87.  Then the 86 goes on to its next
  32. instruction, operating in parallel with the 87.  That's OK, so
  33. long as the following instructions don't do one of the following:
  34.  
  35.   1. Execute another floating point instruction; or
  36.  
  37.   2. Try to read the results of the still-executing floating
  38.      point instruction.
  39.  
  40. If they do, then you must provide an instruction called WAIT (or
  41. synonymously FWAIT), which halts the 86 until the 87 is finished.
  42. For almost all floating point instructions, it should not be
  43. necessary to provide an explicit FWAIT; the 86 ought to know that
  44. it should wait.  For the 8087, it IS necessary to give an
  45. explicit FWAIT before each floating point instruction: that is
  46. the flaw.
  47.  
  48. Because of the flaw, all assemblers supporting the 8087 will
  49. silently insert an FWAIT code (hex 9B) before all 87
  50. instructions, except those few (the FN instructions other than
  51. FNOP) not requiring the FWAIT.  A86 will insert the opcode as
  52. well, when it is assembling for the original 8087.
  53.                                                               7-2
  54.  
  55. The are three ways to tell A86 whether it is assembling for an
  56. 8087 or a 287-or-later processor.  First, A86 will use a default
  57. for the processor on which it is currently assembling: no .287
  58. for an 8086, 8088, 186, or NEC; .287 for a 286 or later.  Second,
  59. this can be overridden by the switch +F (the F must be
  60. capitalized), to signal that the 287 is the target processor, or
  61. -F to specify the 8087.  Third, an 8087 setting can be further
  62. overridden in the source code, with the directive ".287",
  63. compatible with Microsoft's assembler.
  64.  
  65. When A86 is assembling for the 287 or later, it ceases outputting
  66. FWAIT directives that are unnecessary for the 287, ignores the
  67. instructions FENI, FDISI, FNENI, and FNDISI, and honors the
  68. instructions FSETPM and FSTSW AX.
  69.  
  70. WARNING: The most common mistake 87 programmers make is to try to
  71. read the results of an 87 operation in 86 memory, before the
  72. results are ready.  At least on my computer, the system often
  73. crashes when you do this!  If your program runs correctly when
  74. single stepped, but crashes when set loose, then chances are you
  75. need an extra explicit FWAIT somewhere.
  76.  
  77.  
  78. Extra Coprocessor Support
  79.  
  80. A86 now supports two additional coprocessors available for
  81. PC-compatibles: the 80387, available for 386-based machines, and
  82. the IIT-2C87, a 287-plug-compatible chip that adds a couple of
  83. unique instructions. The IIT-2C87 has two extra banks of on-chip
  84. 8-number stacks, that can be switched in with the FBANK
  85. instruction, and a matrix multiply instrction that uses all three
  86. banks as input.  (For details contact Specialty Software
  87. Development Corp., 110 Wild Basin Road, Austin TX 78746.) Both
  88. chips incorporate the correction to the 8087's FWAIT design flaw,
  89. so you can assemble with the .287 directive.  The extra
  90. instructions for these chips are marked by "387 only:" and "IIT
  91. only:" in the chart at the end of this chapter.
  92.  
  93.  
  94. Emulating the 8087 by Software
  95.  
  96. There is a software package provided with many compilers
  97. (Borland's Turbo C and most Microsoft compilers, for example)
  98. that emulates the 8087 instruction set.  The emulator is very
  99. cleverly implemented so that the programmer need not know whether
  100. a floating point chip will be available, or whether emulation
  101. will be necessary.  This is done by having the linker replace all
  102. floating point machine instructions with INT calls to certain
  103. interrupts, dedicated to emulation.  The interrupt handlers
  104. interpret the operands to the instructions, and emulate the 8087.
  105.                                                               7-3
  106.  
  107. You can tell A86 that the emulator might be used, by providing a
  108. +f switch in the invocation line, or in the A86 environment
  109. variable (make sure the f is lower case).  Since your program
  110. will be linked to the emulator, you must be producing an OBJ
  111. file, not a COM file, for emulation support to take effect.
  112. Whenever a floating point instruction is assembled, A86 will
  113. generate an external reference at the opcode for the instruction.
  114. Then, if the emulation package is linked with your program, the
  115. opcodes will be replaced by the INT calls. If a special
  116. non-emulation module is linked, the opcodes will be left alone,
  117. and the floating point instructions will be executed directly.
  118.  
  119. For the later processors (286 and beyond), emulation can be
  120. provided that executes when the floating-point instructions
  121. themselves are seen, so the +f games are not necessary.
  122.  
  123.  
  124. The Floating Point Stack
  125.  
  126. The 87 has its own register set, of 8 floating point numbers
  127. occupying 10 bytes each, plus 14 bytes of status and control
  128. information.  Many of the 87's instructions cause the numbers to
  129. act like a stack, much like a Hewlett-Packard calculator.  For
  130. this reason, the numbers are called the floating point stack.
  131.  
  132. The standard name for the top element of the floating point stack
  133. is either ST or ST(0); the others are named ST(1) through ST(7).
  134. Thus, for example, the instruction to add stack element number 3
  135. into the top stack element is usually coded FADD ST,ST(3).
  136.  
  137. I find this notation painfully verbose.  Especially bad are the
  138. parentheses, which are hard to type, and which add visual clutter
  139. to the program.  To alleviate this problem while retaining
  140. language compatibility, I name my stack elements simply 0 through
  141. 7.  I recognize ST as a synonym for 0.  I allow expression
  142. elements to be concatenated; concatenation is the same as
  143. addition.  Thus, when A86 sees ST(3), it computes 0+3 = 3.  So
  144. you can code the old way, FADD ST,ST(3), or you can code the
  145. concise way, FADD 0,3 or simply FADD 3.
  146.  
  147.  
  148. Floating Point Initializations
  149.  
  150. In general, you use the 87 by loading numbers from 86 memory to
  151. the 87 stack (using FLD instructions), calculating on the 87
  152. stack, and storing the results back to 86 memory (using FST and
  153. FSTP instructions).  There are seven constant numbers built into
  154. the 87 instruction set: zero, one, Pi, and four logarithmic
  155. conversion constants.  These can be loaded using the FLD0, FLD1,
  156. FLDPI, FLDL2T, FLDL2E, FLDLG2, and FLDLN2 instructions.  All
  157. other constants must be declared in, then loaded from, 86 memory.
  158. Integer constant words and doublewords can be loaded via FILD.
  159. Non-integer constant doubleword, quadwords, and ten-byte numbers
  160. can be loaded via FLD.
  161.                                                               7-4
  162.  
  163. A86 allows you to declare constants loaded via FLD as floating
  164. point numbers, using scientific notation if you like.  As an
  165. exclusive feature, A86 allows you to use any of the 4 arithmetic
  166. functions +, -, *, / in expressions involving floating point
  167. numbers.  A86 will even do type conversion if one of the two
  168. o